package models

import (
	"encoding/json"
	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/logs"
	"github.com/jinzhu/copier"
	"sort"
	"strconv"
	"strings"
	productEnum "yixiang.co/yshop/common/enums/product"
	"yixiang.co/yshop/common/untils"
	"yixiang.co/yshop/models/dto"
)

type YshopStoreProduct struct {
	Id          int64  `json:"id"`
	Image       string `json:"image" valid:"Required;"`
	SliderImage string `json:"sliderImage" valid:"Required;"`
	StoreName   string `json:"storeName" valid:"Required;"`
	StoreInfo   string `json:"storeInfo" valid:"Required;"`
	Keyword     string `json:"keyword" valid:"Required;"`
	//CateId 			string `json:"cateId" valid:"Required;"`
	ProductCate  *YshopStoreCategory `json:"productCate" orm:"column(cate_id);rel(one)""`
	Price        float64             `json:"price" valid:"Required;"`
	VipPrice     float64             `json:"vipPrice" valid:"Required;"`
	OtPrice      float64             `json:"otPrice" valid:"Required;"`
	Postage      float64             `json:"postage" valid:"Required;"`
	UnitName     string              `json:"unitName" valid:"Required;"`
	Sort         int16               `json:"sort" valid:"Required;"`
	Sales        int                 `json:"sales" valid:"Required;"`
	Stock        int                 `json:"stock" valid:"Required;"`
	IsShow       int8                `json:"isShow" valid:"Required;"`
	IsHot        int8                `json:"isHot" valid:"Required;"`
	IsBenefit    int8                `json:"is_benefit" valid:"Required;"`
	IsBest       int8                `json:"isBest" valid:"Required;"`
	IsNew        int8                `json:"isNew" valid:"Required;"`
	Description  string              `json:"description" valid:"Required;"`
	IsPostage    int8                `json:"isPostage" valid:"Required;"`
	GiveIntegral float64             `json:"giveIntegral" valid:"Required;"`
	Cost         float64             `json:"cost" valid:"Required;"`
	IsGood       int8                `json:"isGood" valid:"Required;"`
	Ficti        int                 `json:"ficti" valid:"Required;"`
	Browse       int                 `json:"browse" valid:"Required;"`
	IsSub        int8                `json:"isSub" valid:"Required;"`
	TempId       int64               `json:"tempId" valid:"Required;"`
	SpecType     int8                `json:"specType" valid:"Required;"`
	IsIntegral   int8                `json:"isIntegral" valid:"Required;"`
	Integral     int32               `json:"integral" valid:"Required;"`
	BaseModel
}

func init() {
	orm.RegisterModel(new(YshopStoreProduct))
}

// get all
func GetAllProduct(base dto.BasePage, query ...interface{}) (int, []YshopStoreProduct) {
	var (
		tableName = "yshop_store_product"
		data      []YshopStoreProduct
		condition = ""
	)
	if base.Blurry != "" {
		condition = " and store_name= '" + base.Blurry + "'"
	}
	if len(query) > 0 {
		isShow := query[0].(int)
		if isShow > -1 {
			condition += " and is_show=" + strconv.Itoa(isShow)
		}
	}

	total, _, rs := GetPagesInfo(tableName, base.Page, base.Size, condition)
	rs.QueryRows(&data)

	o := orm.NewOrm()
	for k, _ := range data {
		_, _ = o.LoadRelated(&data[k], "ProductCate")
	}

	return total, data
}

func GetProductInfo(id int64) map[string]interface{} {
	var (
		mapData           = make(map[string]interface{})
		yshopStoreProduct YshopStoreProduct
		productDto        dto.StoreProductInfo
	)

	catList := GetProductCate()
	param := dto.BasePage{Page: 1, Size: 9999, Blurry: ""}
	_, ruleList := GetAllProductRule(param)
	mapData["cateList"] = catList
	mapData["ruleList"] = ruleList
	if id == 0 {
		return mapData
	}

	o := orm.NewOrm()
	e := o.QueryTable(new(YshopStoreProduct)).Filter("id", id).RelatedSel().One(&yshopStoreProduct)
	logs.Error(e)
	copier.Copy(&productDto, yshopStoreProduct)
	productDto.CateId = yshopStoreProduct.ProductCate.Id
	productDto.SliderImage = strings.Split(yshopStoreProduct.SliderImage, ",")
	res := GetProductAttrResult(id)
	productDto.Attrs = res["value"]
	productDto.Items = res["attr"]

	mapData["productInfo"] = productDto

	return mapData
}

func AddOrSaveProduct(m *dto.StoreProduct) (id int64, err error) {
	var (
		model     YshopStoreProduct
		productId int64
	)
	copier.Copy(&model, &m)

	res := computeProduct(m.Attrs)
	model.Price = res["minPrice"].(float64)
	model.OtPrice = res["minOtPrice"].(float64)
	model.Cost = res["minCost"].(float64)
	model.Stock = res["stock"].(int)
	images := strings.Join(m.SliderImage, ",")
	model.SliderImage = images
	model.ProductCate = &YshopStoreCategory{
		Id: m.CateId,
	}

	if m.Id > 0 {
		err = UpdateByProduct(&model)
		id = 0
		productId = m.Id
	} else {
		o := orm.NewOrm()
		id, err = o.Insert(&model)
		productId = id
		logs.Error(err)
	}

	//sku处理
	if m.SpecType == productEnum.SEPC_TYPE_0 {
		list1 := []string{"默认"}
		formatDetail := dto.FormatDetail{
			Value:  "规格",
			Detail: list1,
		}
		productFormat := m.Attrs[0]
		productFormat.Value1 = "规格"
		productFormat.Detail = map[string]string{
			"规格": "默认",
		}
		err = insertProductSku([]dto.FormatDetail{formatDetail}, []dto.ProductFormat{productFormat}, productId)
		logs.Error(err)
	} else {
		err = insertProductSku(m.Items, m.Attrs, productId)
	}
	return id, err
}

func UpdateByProduct(m *YshopStoreProduct) (err error) {
	o := orm.NewOrm()
	_, err = o.Update(m)
	return
}

func OnSaleByProduct(id int64, status int) (err error) {
	o := orm.NewOrm()
	var isShow = 0
	if status == 0 {
		isShow = 1
	}
	_, err = o.QueryTable(new(YshopStoreProduct)).Filter("id", id).Update(orm.Params{
		"is_show": isShow,
	})
	return
}

func DelByProduct(ids []int64) (err error) {
	str := untils.ReturnQ(len(ids))
	logs.Info(str)
	o := orm.NewOrm()
	_, err = o.Raw("UPDATE yshop_store_product SET is_del = ? WHERE id in("+str+")", 1, ids).Exec()
	return
}

//获取生成的商品sku
func GetFormatAttr(id int64, jsonObj map[string]interface{}) map[string]interface{} {
	var (
		mapData          = make(map[string]interface{})
		formatDetailList []dto.FormatDetail
		headerMapList    []map[string]interface{}
		valueMapList     []map[string]interface{}
		align            string = "center"
	)

	jsonByte, _ := json.Marshal(jsonObj["attrs"])
	json.Unmarshal(jsonByte, &formatDetailList)
	//logs.Info(formatDetailList)

	arr, ok := jsonObj["attrs"].([]interface{})
	if ok && len(arr) == 0 {
		return mapData
	}

	detail := attrFormat(formatDetailList)

	count := 0
	for _, mapData := range detail.Res {
		detailMap := mapData["detail"]
		valueMap := make(map[string]interface{})

		//组合表格头
		var i int = 0
		logs.Info(detailMap)
		if count == 0 {
			for kk, _ := range detailMap {
				headerMap := make(map[string]interface{})
				headerMap["title"] = kk
				headerMap["minWidth"] = 130
				headerMap["align"] = align
				myIntStr := strconv.Itoa(i + 1)
				headerMap["key"] = "value" + myIntStr
				headerMap["slot"] = "value" + myIntStr
				headerMapList = append(headerMapList, headerMap)
				i++
			}

			count++
		}

		//组合值
		j := 0
		skuArr := make([]string, 0, len(headerMapList))
		for _, kk := range headerMapList {
			key := "value" + strconv.Itoa(j+1)

			v := detailMap[kk["title"].(string)]
			valueMap[key] = detailMap[kk["title"].(string)]
			j++
			skuArr = append(skuArr, v)
		}
		sort.Strings(skuArr)
		sku := strings.Join(skuArr, ",")
		logs.Info("sku:" + sku)
		valueMap["detail"] = detailMap
		valueMap["pic"] = ""
		valueMap["price"] = 0
		valueMap["cost"] = 0
		valueMap["ot_price"] = 0
		valueMap["stock"] = 0
		valueMap["bar_code"] = ""
		valueMap["weight"] = 0
		valueMap["volume"] = 0
		//valueMap["brokerage"] = 0
		//valueMap["brokerage_two"] = 0
		//valueMap["pink_price"] = 0
		//valueMap["seckill_price"] = 0
		//valueMap["piink_stock"] = 0
		//valueMap["seckill_stock"] = 0
		if id > 0 {
			storeProductAttrValue := GetAttrValueByProductIdAndSku(id, sku)

			valueMap["pic"] = storeProductAttrValue.Image
			valueMap["price"] = storeProductAttrValue.Price
			valueMap["cost"] = storeProductAttrValue.Cost
			valueMap["ot_price"] = storeProductAttrValue.Price
			valueMap["stock"] = storeProductAttrValue.Stock
			valueMap["bar_code"] = storeProductAttrValue.BarCode
			valueMap["weight"] = storeProductAttrValue.Weight
			valueMap["volume"] = storeProductAttrValue.Volume
			valueMap["brokerage"] = storeProductAttrValue.Brokerage
			valueMap["brokerage_two"] = storeProductAttrValue.BrokerageTwo
			valueMap["pink_price"] = storeProductAttrValue.PinkPrice
			valueMap["seckill_price"] = storeProductAttrValue.SeckillPrice
			valueMap["piink_stock"] = storeProductAttrValue.PinkStock
			valueMap["seckill_stock"] = storeProductAttrValue.SeckillStock
		}

		valueMapList = append(valueMapList, valueMap)
	}

	headerMapList = addMap(headerMapList, align)

	mapData["attr"] = formatDetailList
	mapData["value"] = valueMapList
	mapData["header"] = headerMapList

	return mapData
}

//组合map
func addMap(headerMapList []map[string]interface{}, align string) []map[string]interface{} {

	headMap := map[string]interface{}{
		"title":    "图片",
		"slot":     "pic",
		"align":    align,
		"minWidth": 80,
	}
	headerMapList = append(headerMapList, headMap)

	headMap = map[string]interface{}{
		"title":    "售价",
		"slot":     "price",
		"align":    align,
		"minWidth": 120,
	}
	headerMapList = append(headerMapList, headMap)

	headMap = map[string]interface{}{
		"title":    "成本价",
		"slot":     "cost",
		"align":    align,
		"minWidth": 140,
	}
	headerMapList = append(headerMapList, headMap)

	headMap = map[string]interface{}{
		"title":    "原价",
		"slot":     "ot_price",
		"align":    align,
		"minWidth": 140,
	}
	headerMapList = append(headerMapList, headMap)

	headMap = map[string]interface{}{
		"title":    "库存",
		"slot":     "stock",
		"align":    align,
		"minWidth": 140,
	}
	headerMapList = append(headerMapList, headMap)

	headMap = map[string]interface{}{
		"title":    "产品编号",
		"slot":     "bar_code",
		"align":    align,
		"minWidth": 140,
	}
	headerMapList = append(headerMapList, headMap)

	headMap = map[string]interface{}{
		"title":    "重量(kg)",
		"slot":     "weight",
		"align":    align,
		"minWidth": 140,
	}
	headerMapList = append(headerMapList, headMap)

	headMap = map[string]interface{}{
		"title":    "体积(m³)",
		"slot":     "volume",
		"align":    align,
		"minWidth": 140,
	}
	headerMapList = append(headerMapList, headMap)

	headMap = map[string]interface{}{
		"title":    "操作",
		"slot":     "action",
		"align":    align,
		"minWidth": 70,
	}
	headerMapList = append(headerMapList, headMap)

	return headerMapList

}

//组合sku规则算法
func attrFormat(formatDetailList []dto.FormatDetail) dto.Detail {
	var (
		data []string
		res  []map[string]map[string]string
	)

	if len(formatDetailList) > 1 { //当多个规则时候
		for i := 0; i < len(formatDetailList)-1; i++ {
			if i == 0 {
				data = formatDetailList[i].Detail
			}

			var tmp []string
			for _, v := range data {
				for _, g := range formatDetailList[i+1].Detail {
					rep2 := ""
					if i == 0 {
						rep2 = formatDetailList[i].Value + "_" + v + "-" + formatDetailList[i+1].Value + "_" + g
					} else {
						rep2 = v + "-" + formatDetailList[i+1].Value + "_" + g
					}

					tmp = append(tmp, rep2)

					if i == len(formatDetailList)-2 {
						var (
							rep4    = make(map[string]map[string]string)
							reptemp = make(map[string]string)
						)
						for _, h := range strings.Split(rep2, "-") {
							rep3 := strings.Split(h, "_")
							if len(rep3) > 1 {
								reptemp[rep3[0]] = rep3[1]
							} else {
								reptemp[rep3[0]] = ""
							}
						}

						rep4["detail"] = reptemp
						res = append(res, rep4)

					}

				}
			}

			if len(tmp) > 0 {
				data = tmp
			}

		}
	} else { //一个规则时候
		var dataArr []string
		for _, formatDetail := range formatDetailList {
			for _, str := range formatDetail.Detail {
				var map2 = make(map[string]map[string]string)
				dataArr = append(dataArr, formatDetail.Value+"_"+str)
				map1 := map[string]string{
					formatDetail.Value: str,
				}
				map2["detail"] = map1

				res = append(res, map2)
			}
		}

		s := strings.Join(dataArr, "-")
		data = append(data, s)
	}

	return dto.Detail{
		Data: data,
		Res:  res,
	}
}

//计算获取属性结果最小值
func computeProduct(attrs []dto.ProductFormat) map[string]interface{} {
	returnMap := make(map[string]interface{})

	var (
		minPrice   []float64
		minOtprice []float64
		minCost    []float64
		stock      []int
	)
	for _, dto := range attrs {
		price, _ := strconv.ParseFloat(dto.Price, 64)
		OtPrice, _ := strconv.ParseFloat(dto.Price, 64)
		cost, _ := strconv.ParseFloat(dto.Price, 64)
		s, _ := strconv.Atoi(dto.Stock)
		minPrice = append(minPrice, price)
		minOtprice = append(minOtprice, OtPrice)
		minCost = append(minCost, cost)
		stock = append(stock, s)
	}
	sort.Float64s(minPrice)
	sort.Float64s(minOtprice)
	sort.Float64s(minCost)
	returnMap["minPrice"] = minPrice[0]
	returnMap["minOtPrice"] = minOtprice[0]
	returnMap["minCost"] = minCost[0]
	returnMap["stock"] = untils.GetSum(stock)
	return returnMap
}

func insertProductSku(items []dto.FormatDetail, attrs []dto.ProductFormat, productId int64) (err error) {
	DelByProductttr(productId)
	DelByProductttrValue(productId)
	err = AddProductAttr(items, productId)
	if err != nil {
		return err
	}

	err = AddProductttrValue(attrs, productId)
	if err != nil {
		return err
	}
	_, err = AddProductAttrResult(items, attrs, productId)
	if err != nil {
		return err
	}

	return

}
